package com.vben.system.biz.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vben.common.exception.enums.ErrorCode;
import com.vben.common.exception.system.user.UserException;
import com.vben.system.api.dto.rbac.RemoveUserRoleDTO;
import com.vben.system.api.dto.rbac.RoleIdDTO;
import com.vben.system.api.dto.rbac.SaveUserRoleDTO;
import com.vben.system.api.dto.user.SysUserPageDTO;
import com.vben.system.api.entity.SysRoleMenu;
import com.vben.system.api.entity.SysUser;
import com.vben.system.api.entity.SysUserRole;
import com.vben.system.api.vo.user.SysUserVO;
import com.vben.system.biz.mapper.SysRoleMenuMapper;
import com.vben.system.biz.service.SysRbacService;
import com.vben.system.biz.service.SysUserRoleService;
import com.vben.system.biz.service.SysUserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * RBAC 相关业务实现
 */
@Service
public class SysRbacServiceImpl implements SysRbacService {

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserService sysUserService;

    @Override
    public List<Long> getRoleMenuIds(Long roleId) {
        QueryWrapper<SysRoleMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        List<SysRoleMenu> roleMenus = sysRoleMenuMapper.selectList(wrapper);
        if (roleMenus == null) {
            return Collections.emptyList();
        }
        return roleMenus.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());
    }

    @Override
    public Boolean saveRoleMenu(Long roleId, List<Long> menuIds) {
        // 删除原有的角色菜单关联
        QueryWrapper<SysRoleMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        sysRoleMenuMapper.delete(wrapper);

        // 插入新的角色菜单关联
        if (menuIds != null && !menuIds.isEmpty()) {
            for (Long menuId : menuIds) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                sysRoleMenuMapper.insert(roleMenu);
            }
        }
        return true;
    }

    @Override
    public Page<SysUser> getUserListByRoleId(RoleIdDTO param) {
        Long roleId = param.getRoleId();
        if (roleId == null) {
            throw new UserException(ErrorCode.PARAM_INVALID);
        }
        List<SysUserRole> userRoles = sysUserRoleService.lambdaQuery().eq(SysUserRole::getRoleId, roleId).list();
        List<Long> userIds = userRoles.stream().map(SysUserRole::getUserId).toList();
        if (userIds.isEmpty()) {
            return new Page<>();
        }
        SysUserPageDTO userPageParam = new SysUserPageDTO();
        userPageParam.setPageNum(param.getPageNum());
        userPageParam.setPageSize(param.getPageSize());
        userPageParam.setUserIds(userIds);
        return sysUserService.pageVO(userPageParam);
    }

    @Override
    public Boolean removeUserRole(List<RemoveUserRoleDTO> dtoList) {
        if (CollUtil.isEmpty(dtoList)) {
            return true;
        }
        for (RemoveUserRoleDTO dto : dtoList) {
            Long roleId = dto.getRoleId();
            Long userId = dto.getUserId();
            if (roleId == null || userId == null) {
                continue;
            }

            LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(SysUserRole::getRoleId, roleId).eq(SysUserRole::getUserId, userId);
            sysUserRoleService.remove(lambdaQueryWrapper);
        }

        return true;
    }

    @Override
    public Page<SysUserVO> getUserListExcludeRoleId(RoleIdDTO dto) {
        Long roleId = dto.getRoleId();
        if (roleId == null) {
            throw new UserException(ErrorCode.PARAM_INVALID);
        }
        List<SysUserRole> userRoles = sysUserRoleService.lambdaQuery().eq(SysUserRole::getRoleId, roleId).list();
        List<Long> userIds = userRoles.stream().map(SysUserRole::getUserId).toList();
        Page<SysUser> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        // 排除已关联的用户
        Page<SysUser> userPage = sysUserService.lambdaQuery().notIn(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds).page(page);
        List<SysUser> userList = userPage.getRecords();
        if (userList.isEmpty()) {
            return new Page<>();
        }
        List<SysUserVO> vos = userList.stream().map(item -> sysUserService.toVO(item)).toList();
        Page<SysUserVO> pageVO = new Page<>();
        pageVO.setTotal(userPage.getTotal());
        pageVO.setRecords(vos);
        return pageVO;
    }

    @Override
    public Boolean saveUserRole(List<SaveUserRoleDTO> dtoList) {

        if (CollUtil.isEmpty(dtoList)) {
            return true;
        }

        for (SaveUserRoleDTO dto : dtoList) {
            Long roleId = dto.getRoleId();
            Long userId = dto.getUserId();
            if (roleId == null || userId == null) {
                throw new UserException(ErrorCode.PARAM_INVALID);
            }
            // 检查是否已存在该用户角色关联
            LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysUserRole::getRoleId, roleId).eq(SysUserRole::getUserId, userId);
            SysUserRole existing = sysUserRoleService.getOne(wrapper);
            if (existing == null) {
                SysUserRole userRole = new SysUserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(userId);
                sysUserRoleService.save(userRole);
            }
        }
        return true;
    }
}